package com.atguigu.yygh.cmn.service.impl;

import com.alibaba.excel.EasyExcel;
import com.atguigu.yygh.cmn.listener.DictListener;
import com.atguigu.yygh.cmn.mapper.DictMapper;
import com.atguigu.yygh.cmn.service.DictService;
import com.atguigu.yygh.common.exception.YyghException;
import com.atguigu.yygh.common.result.ResultCode;
import com.atguigu.yygh.common.result.ResultCodeEnum;
import com.atguigu.yygh.model.cmn.Dict;
import com.atguigu.yygh.vo.cmn.DictEeVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mysql.cj.x.protobuf.MysqlxExpr;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 组织架构表 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2022-12-15
 */
@Service
@Slf4j
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {


    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 根据数据id查询子数据列表
     *
     * @param id
     * @return
     */
    @Override
    @Cacheable(key = "#id", value = "dict", unless = "#result == null")
    public List<Dict> findChildData(Long id) {
        //根据parent_id查找子记录
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", id);
        List<Dict> dictList = baseMapper.selectList(wrapper);
        //向list集合每个dict对象中设置hasChildren
        for (Dict dict : dictList) {
            Long dictId = dict.getId();
            boolean isChild = this.hashChildren(dictId);
            dict.setHasChildren(isChild);
        }
        return dictList;
    }
   /* @Override
    public List<Dict> findChildData(Long id) {

        // 从redis中查找，如果存在则直接返回，如果不存在就去数据库中查找,然后保存到redis中
        List<Dict> dictList = null;
        try {
            dictList = (List<Dict>) redisTemplate.opsForValue().get("dictList:" + id);
            // 如果有直接返回
            if (dictList != null) {
                return dictList;
            }
        } catch (Exception e) {
            // redis出问题不用抛异常，直接用数据库操作即可
            log.info("redis服务器异常：get dictList");
        }
        //根据parent_id查找子记录
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", id);
        dictList = baseMapper.selectList(wrapper);
        //向list集合每个dict对象中设置hasChildren
        for (Dict dict : dictList) {
            Long dictId = dict.getId();
            boolean isChild = this.hashChildren(dictId);
            dict.setHasChildren(isChild);
        }
        // 保存到redis中
        try {
            redisTemplate.opsForValue().set("dictList:" + id, dictList, 5, TimeUnit.MINUTES);
        } catch (Exception e) {
            log.info("redis服务器异常：save dictList");
        }
        return dictList;
    }*/


    /**
     * 获取所有需要导出的数据
     *
     * @return
     */
    @Override
    public List<DictEeVo> findExportData() {
        List<Dict> dictList = baseMapper.selectList(null);
        List<DictEeVo> dictVoList = new ArrayList<>(dictList.size());
        for (Dict dict : dictList) {
            DictEeVo dictVo = new DictEeVo();
            BeanUtils.copyProperties(dict, dictVo);
            dictVoList.add(dictVo);
        }
        return dictVoList;
    }

    /**
     * 判断id下面是否有子节点
     *
     * @param id
     * @return
     */
    private boolean hashChildren(Long id) {
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", id);
        Integer count = baseMapper.selectCount(wrapper);
        return count > 0;
    }

    @Override
    public void importDictData(MultipartFile file) {
        try {
            long b = System.currentTimeMillis();
            EasyExcel.read(file.getInputStream(), DictEeVo.class, new DictListener(baseMapper)).sheet().doRead();
            long e = System.currentTimeMillis();

            log.info("用时：" + (e - b) + "ms");
        } catch (IOException e) {
            throw new YyghException(ResultCode.ERROR, "数据导入错误", e);
        }
    }

    @Override
    @CachePut(key = "#dict.id", value = "dict") // 执行方法体，将结果还存起来
    public Dict saveDictWithCacheManager(Dict dict) {
        baseMapper.insert(dict);
        return dict;
    }

    @Override
    @CacheEvict(value = "dict", key = "#id") // key是形式参数
    public void deleteDictWithCacheManager(Long id) {
        baseMapper.deleteById(id);
    }

    @Override
    @Cacheable(value = "dict", key = "#id", unless = "#result == null") // redis中有就直接返回，没有去数据库中查找，然后保存到redis,数据不存在也会缓存
    public Dict getDictWithCacheManager(Long id) {
        return baseMapper.selectById(id);
    }

    @Override
    public List<Map<String, Object>> findByParentDictCode(String parentDictCode) {
        QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dict_code", parentDictCode);
        Dict parentDict = baseMapper.selectOne(queryWrapper);
        if (parentDict == null) {
            throw new YyghException(ResultCodeEnum.NO_DATA_EXIST);
        }
        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", parentDict.getId());
        List<Map<String, Object>> dictList = baseMapper.selectMaps(queryWrapper);
        return dictList;
    }

    /**
     * 根据上级编码与当前值获取数据字典名称
     *
     * @param parentDictCode
     * @param value
     * @return
     */
    @Override
    public String getNameByParentDictCodeAndValue(String parentDictCode, String value) {
        if (!StringUtils.isEmpty(parentDictCode)) {
            QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("dict_code", parentDictCode);
            Dict parentDict = baseMapper.selectOne(queryWrapper);
            if (parentDict == null) {
                return "";
            }
            queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("parent_id", parentDict.getId()).eq("value", value);
            Dict dict = baseMapper.selectOne(queryWrapper);
            if (dict == null) {
                return "";
            }
            return dict.getName();
        }
        QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("value", value);
        Dict dict = baseMapper.selectOne(queryWrapper);

        return Objects.isNull(dict) ? "" : dict.getName();
    }

}
